﻿Imports System.Activities
Imports System.ComponentModel
Imports System.Activities.Presentation.PropertyEditing
Imports System.Activities.Presentation.Metadata
Imports System.Drawing

Public Class ExecuteApplicationActivity
    Inherits AsyncCodeActivity
    Implements IRegisterMetadata

    ''' <summary>DOSコマンド実行時のプロセス</summary><exclude />
    Private Const DOSCOMMAND_FILENAME As String = "ComSpec"
    ''' <summary>DOSコマンド実行時の必須引数</summary><exclude />
    Private Const DOSCOMMAND_DEFAULTARGUMENT As String = "/c "

    Public Property TargetFile As InArgument(Of String)
    Public Property Arguments As InArgument(Of String)
    Public Property AsyncExecute As InArgument(Of Boolean) = False
    Public Property OSCommand As InArgument(Of Boolean) = False
    Public Property Result As OutArgument(Of Integer)

    Private Delegate Function asyncExecuteDelegate(ByVal target As String, ByVal args As String, ByVal async As Boolean, ByVal osCom As Boolean) As Integer

    Public Sub New()
        Me.DisplayName = My.Resources.ExecuteApplicationDisplayName
    End Sub

    Protected Overrides Function BeginExecute(context As System.Activities.AsyncCodeActivityContext, callback As System.AsyncCallback, state As Object) As System.IAsyncResult
        Dim target = context.GetValue(Me.TargetFile)
        Dim args = context.GetValue(Me.Arguments)
        Dim asy = context.GetValue(Me.AsyncExecute)
        Dim osc = context.GetValue(Me.OSCommand)
        Dim asyncExecute = New asyncExecuteDelegate(AddressOf ExecuteFileInPrivate)
        context.UserState = asyncExecute

        Return asyncExecute.BeginInvoke(target, args, asy, osc, callback, state)
    End Function

    Protected Overrides Sub EndExecute(context As System.Activities.AsyncCodeActivityContext, result As System.IAsyncResult)
        Dim asyncExecute = TryCast(context.UserState, asyncExecuteDelegate)
        Dim execResult = asyncExecute.EndInvoke(result)

        context.SetValue(Me.Result, execResult)
    End Sub

    Private Function ExecuteFileInPrivate(ByVal target As String, ByVal args As String, ByVal async As Boolean, ByVal osCom As Boolean) As Integer
        'If Not IO.File.Exists(target) Then Return False
        Dim execResult = 0
        Try
            If osCom Then
                args = target + " " + DOSCOMMAND_DEFAULTARGUMENT + args
                target = System.Environment.GetEnvironmentVariable(DOSCOMMAND_FILENAME)
            End If
            Dim prcInfo = New ProcessStartInfo With {
                .FileName = target,
                .Arguments = args
            }

            Dim prc As New Process With {.StartInfo = prcInfo}

            prc.Start()
            If Not async Then
                prc.WaitForExit()
                execResult = prc.ExitCode
            End If
        Catch ex As Exception
            Throw
        End Try
        Return execResult
    End Function


    Public Sub Register() Implements System.Activities.Presentation.Metadata.IRegisterMetadata.Register
        Dim build As New AttributeTableBuilder
        'ExecuteApplicationActivity Activity
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity),
                                              New ToolboxBitmapAttribute(GetType(ExecuteApplicationActivity), "ExecuteApplication.png"))
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity), "TargetFile",
                                              New RequiredArgumentAttribute,
                                              New EditorAttribute(GetType(FilepathPropertyEditor), GetType(DialogPropertyValueEditor)),
                                              New CategoryAttribute(My.Resources.ExecuteApplicationCategory),
                                              New DisplayNameAttribute(My.Resources.ExecuteApplicationTargetDisplay),
                                              New DescriptionAttribute(My.Resources.ExecuteApplicationTargetDescription))
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity), "Arguments",
                                              New CategoryAttribute(My.Resources.ExecuteApplicationCategory),
                                              New DisplayNameAttribute(My.Resources.ExecuteApplicationArgumentsDisplay),
                                              New DescriptionAttribute(My.Resources.ExecuteApplicationArgumentsDescription))
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity), "AsyncExecute",
                                              New RequiredArgumentAttribute,
                                              New EditorAttribute(GetType(InArgumentBoolPropertyEditor), GetType(PropertyValueEditor)),
                                              New CategoryAttribute(My.Resources.ExecuteApplicationCategory),
                                              New DisplayNameAttribute(My.Resources.ExecuteApplicationAsyncExecuteDisplay),
                                              New DescriptionAttribute(My.Resources.ExecuteApplicationAsyncExecuteDescription))
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity), "OSCommand",
                                              New RequiredArgumentAttribute,
                                              New EditorAttribute(GetType(InArgumentBoolPropertyEditor), GetType(PropertyValueEditor)),
                                              New CategoryAttribute(My.Resources.ExecuteApplicationCategory),
                                              New DisplayNameAttribute(My.Resources.ExecuteApplicationOSCommandDisplay),
                                              New DescriptionAttribute(My.Resources.ExecuteApplicationOSCommandDescription))
        build.AddCustomAttributes(GetType(ExecuteApplicationActivity), "Result",
                                              New CategoryAttribute(My.Resources.ExecuteApplicationCategory),
                                              New DisplayNameAttribute(My.Resources.ExecuteApplicationResultsDisplay),
                                              New DescriptionAttribute(My.Resources.ExecuteApplicationResultsDescription))

        MetadataStore.AddAttributeTable(build.CreateTable)
    End Sub

End Class
